package com.jin.webvideo.videoCache;

import com.jin.webvideo.base.util.CollectionsUtil;
import com.jin.webvideo.util.cloneUtil.Cloneable;
import com.jin.webvideo.util.base.StringUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Cloneable()
public class M3U8File {
    private static String template = "#%s:%s\n";
    private static String templateEmpty = "#%s\n";

    private static final int LIST_TYPE_MEDIA = 1;
    private static final int LIST_TYPE_MASTER = 0;

    private String source;
    private int listType;
    private List<TSFile> tsList = new ArrayList<>();
    public M3U8File(){}
    public M3U8File(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        SegmentParam param = null;
        while ( (line = readLine(reader)) != null){

            TSFile ts = new TSFile(this);
            SegmentParam temp = createParam(line);
            if (null == temp){
                ts.setUrl(line.trim());
                ts.addTag(param);
                tsList.add(ts);
            }
            else if (param != null){
                ts.addTag(param);
                tsList.add(ts);
            }
            param = temp;
        }
        if (null != param){
            TSFile ts = new TSFile(this);
            ts.addTag(param);
            tsList.add(ts);
        }
        if (CollectionsUtil.first(this.tsList, (f) -> f.hasTag("EXT-X-STREAM-INF") || f.hasTag("EXT-X-I-FRAME-STREAM-INF")) == null) {
            this.listType = LIST_TYPE_MEDIA;
        }
    }

    public void setSource(String source) {
        this.source = source;
    }

    public String getSource() {
        return source;
    }
    public boolean isMediaList() {
        return this.listType == LIST_TYPE_MEDIA;
    }
    public boolean isPlayList() {
        return this.listType == LIST_TYPE_MASTER;
    }
    public List<TSFile> getMediaSegment() {
        return CollectionsUtil.filter(this.tsList, (c) -> !StringUtil.isEmpty(c.getUrl()));
    }

    public void save(File file, boolean absPath) throws IOException {
        File parent = file.getParentFile();
        if (!parent.exists()){
            throw new FileNotFoundException(parent.getAbsolutePath());
        }
        if (file.exists()){
            file.createNewFile();
        }
        OutputStream stream = null;
        try{
            stream = new FileOutputStream(file);
            OutputStreamWriter writer = new OutputStreamWriter(stream);

            for (TSFile ts : tsList){
                for (SegmentParam tag : ts.getTags()){
                    String temp = template;
                    String value = tag.getStingValue();
                    if (null == value){
                        temp = templateEmpty;
                    }
                    writer.write(String.format(temp, tag.getName(), value));
                }
                if (ts.getUrl() != null){
                    String url = ts.getUrl();
                    if (absPath){
                        url = ts.getAbslotePath();
                    }
                    writer.write(url + "\n");
                }
            }
            writer.flush();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != stream){
                stream.close();
            }
        }
    }

    private SegmentParam createParam(String line){
        SegmentParam param = null;
        if (line.startsWith("#EXT")){
            param = new SegmentParam();
            line = line.substring(1);
            String[] kv = StringUtil.splitWithRegex(line, ":");
            param.setName(StringUtil.trim(kv[0]));
            String[] values = StringUtil.split(StringUtil.trim(kv[1]) , ",");
            for (String value : values){
                kv = StringUtil.splitWithRegex(StringUtil.trim(value), "=");
                param.putValue(StringUtil.trim(kv[0]), StringUtil.trim(kv[1]));
            }
        }
        return param;
    }

    private static String readLine(BufferedReader reader) throws IOException {
        String line = null;
        while ( (line = reader.readLine()) != null){
            if (!line.isEmpty()){
                break;
            }
        }
        return line;
    }
}
